package normalisation;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.regex.Pattern;

public class Normalizer {

    public static enum NormalisationType {

        Tokenisation, Racinisation, Lemmatisation
    }

    public static enum EncodageType {

        UTF_8, ISO_8859_1
    }
    private NormalisationType normalisation;
    private EncodageType encodage;
    private Boolean filterAccents;
    private Boolean filterPonctuation;
    private Boolean filterNombres;
    private Boolean filterStopWords;
    private String stopWordsFilePath;
    private Boolean filterOneOccurence;
    private ArrayList<String> stopWordList;

    public Normalizer(NormalisationType normalisation,
            EncodageType encodage,
            Boolean filterAccents,
            Boolean filterPonctuation,
            Boolean filterNombres,
            Boolean filterStopWords,
            String stopWordsFilePath,
            Boolean filterOneOccurence) {

        this.normalisation = normalisation;
        this.encodage = encodage;
        this.filterAccents = filterAccents;
        this.filterPonctuation = filterPonctuation;
        this.filterNombres = filterNombres;
        this.filterStopWords = filterStopWords;
        this.stopWordsFilePath = stopWordsFilePath;
        this.filterOneOccurence = filterOneOccurence;

        ArrayList<String> stopWordList = null;
    }

    public Charset getCharset() {
        if (encodage == EncodageType.ISO_8859_1) {
            return StandardCharsets.ISO_8859_1;
        }

        return StandardCharsets.UTF_8;
    }

    public Boolean getFilterOneOccurence() {
        return filterOneOccurence;
    }

    public ArrayList<String> normalize(String text) {

        //Remplacer les url avant toute transformation
        
        
        //System.out.println(text);
        ArrayList<String> result = new ArrayList<String>();

        //Tokenisation par défault
        result = (new FrenchTokenizer()).normalize(text);

        //Tokenisation, Racinisation, ou Lemmatisation
        if (normalisation == NormalisationType.Lemmatisation) {
            //TODO
        } else if (normalisation == NormalisationType.Racinisation) {
            result = (new FrenchStemmer()).normalize(text);
        }

        //Filtrages
        if (filterAccents) {
            result = enleverAccents(result);
        }

        if (filterNombres) {
            result = enleverNombres(result);
        }

        if (filterPonctuation) {
            result = enleverPonctuation(result);
        }

        if (filterStopWords) {
            try {
                result = enleverStopWords(result);
            } catch (IOException ex) {
            }
        }

        //Filtrer des cas particulier
        result = enleverCasParticuliers(result);

        return result;
    }

    private ArrayList<String> enleverAccents(ArrayList<String> words) {
        Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");

        ArrayList<String> results = new ArrayList<String>();

        for (String word : words) {
            String nfdNormalizedString = java.text.Normalizer.normalize(word, java.text.Normalizer.Form.NFD);
            results.add(pattern.matcher(nfdNormalizedString).replaceAll(""));
        }

        return results;
    }

    private ArrayList<String> enleverNombres(ArrayList<String> words) {
        ArrayList<String> results = new ArrayList<String>();

        for (String word : words) {
            results.add(word.replaceAll("[0-9]+", ""));
        }

        return results;
    }

    private ArrayList<String> enleverStopWords(ArrayList<String> words) throws IOException {

        Charset ENCODING = StandardCharsets.UTF_8;//Encodage du fichier stop word
        //Path p = Paths.get(this.stopWordsFilePath);

        //Scanner = fucking memory leak, java c'est de la merde...
        //Utiliser BufferedReader à la place

//        try (Scanner scanner = new Scanner(p, ENCODING.name())) {
//            while (scanner.hasNextLine()) {
//                words.remove(scanner.nextLine());
//            }
//            
//            scanner.close();
//        }

        //Lis le fichier
        if (this.stopWordList == null) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(this.stopWordsFilePath), ENCODING));
            String line = null;

            this.stopWordList = new ArrayList<String>();
            while ((line = reader.readLine()) != null) {
                stopWordList.add(line);
                //System.out.println(line);//Bug bizare en lisant la première ligne, un caractère chelou est inséré avant le "a"
            }
            reader.close();
        }

        words.removeAll(stopWordList);

        return words;
    }

    private ArrayList<String> enleverPonctuation(ArrayList<String> words) {

        ArrayList<String> results = new ArrayList<String>();

        for (String word : words) {
            results.add(word.replaceAll("[^\\p{L}\\p{N}]", "").replaceAll("\\s+", ""));
        }

        return results;
    }

    private ArrayList<String> enleverCasParticuliers(ArrayList<String> words) {

        ArrayList<String> special = new ArrayList<String>();
        special.add("");//Mot vide
        special.add("http");

        words.removeAll(special);

        return words;
    }
}
